home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 May: Tool Chest / Developer CD Series Tool Chest (Apple Computer)(May 1999).iso / What's New? / Technical Documentaion / Macintosh Technotes and Q&As / technotes / tn / fdp_1085.hqx / FinderDragPro / FinderStuff.c < prev    next >
Encoding:
Text File  |  1996-12-03  |  17.1 KB  |  666 lines

  1.     //
  2.     //    LEGAL NOTICE
  3.     //    ============
  4.     //
  5.     //     You may incorporate this sample code into your applications
  6.     //     without restriction. This sample code has been provided "AS
  7.     //     IS" and the responsibility for its operation is 100% yours.
  8.     //     You are not permitted to redistribute the source as "Apple
  9.     //     sample code" after having made changes. If you're going to
  10.     //     re-distribute the source, we require that you make it clear
  11.     //     in the source that the code was descended from Apple sample
  12.     //     code, but that you've made changes.
  13.     //
  14.     //    REVISION HISTORY
  15.     //    ================
  16.     //
  17.     //    06/09/95    NG    last touched
  18.     //    08/23/96    PG    stolen from Nitin's old FinderDrag project
  19.     //
  20.     
  21.  
  22. #include <Icons.h>
  23. #include <Aliases.h>
  24. #include <AERegistry.h>
  25. #include <Gestalt.h>
  26. #include <AEPackObject.h>
  27. #include <AEObjects.h>
  28. #include <Errors.h>
  29. #include <TextUtils.h>
  30.  
  31. #include "FinderStuff.h"
  32.  
  33. #define require(x,y) do { if (!(x)) goto y; } while (0)
  34.  
  35. AEDesc pFinderTarget;
  36.  
  37. //----------------------------------------------------------------------------
  38. // BuildHFSDescList
  39. //----------------------------------------------------------------------------
  40.  
  41. /*
  42. OSErr BuildHFSDescList(DragReference theDrag, AEDescList *hfsList)
  43. {
  44.     ItemReference    itemRef;
  45.     Size            dataSize;
  46.     FSSpec            theFile;
  47.     OSErr            err;
  48.     unsigned short    numItems, counter;    
  49.  
  50.     err = AECreateList(NULL, 0, false, hfsList);
  51.  
  52.     CountDragItems(theDrag, &numItems);
  53.         
  54.     for (counter = 1; counter <= numItems; counter++) {
  55.         err = GetDragItemReferenceNumber(theDrag, counter, &itemRef);
  56.  
  57.         dataSize = sizeof(FSSpec);
  58.         err = GetFlavorData(theDrag, kRealSpecItemRef, flavorTypeRealSpec, &theFile, &dataSize, 0);
  59.                                     
  60.         if (err == noErr) {
  61.             //
  62.             // This is an hfs flavor object, put it in the file list.
  63.             //
  64.             err = AddSpecToDescList(hfsList, &theFile);
  65.         }
  66.     }
  67.  
  68.     return err;
  69. }
  70. */
  71.  
  72. //----------------------------------------------------------------------------
  73. // HandleDragCloneMove
  74. //
  75. // Walk the drag items and collect the items in it.  Then move them to
  76. // the location pointed to by the full pathname (only for now, of course).
  77. //----------------------------------------------------------------------------
  78. OSErr HandleDragCloneMove(DragReference theDrag)
  79. {
  80.     AEDescList    fileDescList;
  81.     OSErr        err;
  82.     FSSpec        descSpec;
  83.     Point        globalPt;
  84.     short        modifiers;
  85.     Boolean        moveIt;
  86.     
  87.     moveIt = true;
  88.     err = paramErr;
  89.     require(HaveScriptableFinder(), ScriptableFinderDead);
  90.  
  91.     err = BuildHFSDescList(theDrag, &fileDescList);
  92.     require(err == noErr, BuildHFSDescList);
  93.     
  94.     err = GetDropFSSpec(theDrag, &descSpec);
  95.     require(err == noErr, GetDropFSSpec);
  96.     
  97.     err = GetDragModifiers(theDrag, &modifiers, NULL, NULL);
  98.  
  99.     if (err == noErr)
  100.         moveIt = !(modifiers & optionKey);
  101.  
  102.     (void) GetDragMouse(theDrag, &globalPt, NULL);
  103.     err = CloneMoveDescList(&fileDescList, &descSpec, globalPt, false, moveIt);
  104.  
  105. GetDropFSSpec:
  106. BuildHFSDescList:
  107. ScriptableFinderDead:
  108.     return err;
  109. }
  110.  
  111.  
  112. //----------------------------------------------------------------------------
  113. // FinderIsRunning
  114. //
  115. // Walk the Process Mgr list to check if the Finder is running
  116. //----------------------------------------------------------------------------
  117. Boolean FinderIsRunning()
  118. {
  119.     OSErr            err;
  120.     ProcessInfoRec    pInfo;
  121.     ProcessSerialNumber    psn;
  122.     Boolean            foundIt;
  123.  
  124.     foundIt = false;
  125.     psn.highLongOfPSN = 0; psn.lowLongOfPSN = kNoProcess;
  126.  
  127.     while ((foundIt == false) && (GetNextProcess(&psn) == noErr)) {
  128.         pInfo.processName         = NULL;
  129.         pInfo.processAppSpec     = NULL;
  130.         pInfo.processInfoLength    = sizeof(ProcessInfoRec);
  131.     
  132.         err = GetProcessInformation(&psn, &pInfo);
  133.     
  134.         if ((err == noErr) 
  135.             && (pInfo.processSignature == 'MACS') 
  136.             && (pInfo.processType == 'FNDR'))
  137.             
  138.             foundIt = true;
  139.     }
  140.     
  141.     return foundIt;
  142. }
  143.  
  144.  
  145. //----------------------------------------------------------------------------
  146. // HaveScriptableFinder
  147. //
  148. // We have it if the Gestalt bit is set and the Finder is running
  149. //----------------------------------------------------------------------------
  150. Boolean HaveScriptableFinder()
  151. {
  152.     long         response;
  153.     Boolean        haveScriptableFinder;
  154.     OSErr        err;
  155.  
  156.     haveScriptableFinder = false;
  157.     
  158.     err = Gestalt(gestaltFinderAttr, &response);
  159.     require(err == noErr, Gestalt);
  160.  
  161.     if ((response & (1 << gestaltOSLCompliantFinder)) && (FinderIsRunning()))
  162.         haveScriptableFinder = true;
  163.  
  164. Gestalt:
  165.     return haveScriptableFinder;
  166. }
  167.  
  168.  
  169. //----------------------------------------------------------------------------
  170. // SendAppleEvent
  171. //----------------------------------------------------------------------------
  172. OSErr SendAppleEvent(AppleEvent *ae, AppleEvent *reply, AESendMode sendMode)
  173. {
  174.     AppleEvent    throwAwayReply;
  175.     OSErr        err;
  176.  
  177.     if (reply == NULL) {
  178.         err = AESend(ae, &throwAwayReply, sendMode, 
  179.                     kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
  180.         if (err == noErr)
  181.             AEDisposeDesc(&throwAwayReply);
  182.     }
  183.     else
  184.         err = AESend(ae, reply, sendMode, 
  185.                     kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
  186.  
  187.     return err;
  188. }
  189.  
  190.  
  191. //----------------------------------------------------------------------------
  192. // MakeAppleEvent
  193. //----------------------------------------------------------------------------
  194. OSErr MakeAppleEvent(AEEventClass aeClass, AEEventID aeID, 
  195.             AEDesc *target, AppleEvent *ae)
  196. {
  197.     OSErr err = noErr;
  198.  
  199.     if (target->dataHandle == nil)
  200.     {
  201.         DescType finderSig = 'MACS';
  202.  
  203.         err = AECreateDesc(typeApplSignature, (Ptr) &finderSig,
  204.             sizeof(DescType), target);
  205.     }
  206.  
  207.     if (!err)
  208.         err = AECreateAppleEvent(aeClass, aeID, target, 
  209.             kAutoGenerateReturnID, kAnyTransactionID, ae);
  210.     
  211.     return err;
  212. }
  213.  
  214.  
  215. //----------------------------------------------------------------------------
  216. // AddSpecToDescList
  217. //
  218. // Pass this a created descriptor list.
  219. //----------------------------------------------------------------------------
  220. OSErr AddSpecToDescList(AEDescList *descList, FSSpecPtr theSpec)
  221. {
  222.     OSErr    err;
  223.     AEDesc    fileDesc;
  224.     AliasHandle    fileAlias;
  225.  
  226.     // Init the desc handles    
  227.     fileAlias                    = NULL;
  228.     fileDesc.dataHandle            = NULL;
  229.                     
  230.     err = NewAlias(NULL, theSpec, &fileAlias);
  231.     require(err == noErr, NewAlias);
  232.  
  233.     HLock((Handle) fileAlias);
  234.     err = AECreateDesc(typeAlias, (Ptr) *fileAlias, 
  235.                 GetHandleSize((Handle) fileAlias), &fileDesc);
  236.     HUnlock((Handle) fileAlias);
  237.     require(err == noErr, AECreateDesc);
  238.  
  239.     err = AEPutDesc(descList, 0, &fileDesc);
  240.  
  241. AECreateDesc:
  242. NewAlias:
  243.     if (fileDesc.dataHandle != NULL)    (void) AEDisposeDesc(&fileDesc);
  244.     if (fileAlias != NULL)                DisposeHandle((Handle) fileAlias);
  245.     
  246.     return err;
  247. }
  248.  
  249.  
  250. //----------------------------------------------------------------------------
  251. // MakeSpecifierForSelection
  252. //----------------------------------------------------------------------------
  253.  
  254. static OSErr MakeSpecifierForSelection(AEDesc *selectionSpecifier)
  255. {
  256.     OSErr         err;
  257.     DescType     descData;
  258.     AEDesc        keyData, nullDescriptor;
  259.     
  260.     nullDescriptor.descriptorType = typeNull;
  261.     nullDescriptor.dataHandle = NULL;
  262.  
  263.     //
  264.     // Make a descriptor whose type is 'typeType' and whose
  265.     // contents are 'pSelection' (defined in FinderRegistry.h).
  266.     // This descriptor specifies the property of the null container
  267.     // that we are interested in--in this case, the selection.
  268.     //
  269.     descData = pSelection;
  270.     err = AECreateDesc(typeType, (Ptr) &descData, sizeof(DescType), &keyData);
  271.     require(err == noErr, AECreateDesc);
  272.     
  273.     err = CreateObjSpecifier(cProperty, &nullDescriptor, formPropertyID,
  274.                                     &keyData, true, selectionSpecifier);
  275.  
  276. AECreateDesc:
  277.     return err;
  278. }
  279.  
  280.  
  281. //----------------------------------------------------------------------------
  282. // GetIconSuiteFromFinder
  283. //
  284. // Send a GetData AE for the 'ifam'
  285. //----------------------------------------------------------------------------
  286. OSErr GetIconSuiteFromFinder(FSSpecPtr hfsObj, Handle *iconSuite)
  287. {
  288.     OSErr        err;
  289.     AppleEvent    finderEvent, replyEvent;
  290.     AEDesc        fileSpecifier, iconPropertySpecifier;
  291.     DescType    returnType;
  292.     Size        returnSize;
  293.     long        returnLong;
  294.     AEDesc        iconFamily;
  295.  
  296.     //
  297.     // Set up our locals for easy cleanup
  298.     //
  299.     *iconSuite = NULL;
  300.  
  301.     //
  302.     // Make sure the Finder is scriptable and is running.
  303.     //
  304.     err = paramErr;
  305.     require(HaveScriptableFinder() == true, HaveScriptableFinder);
  306.  
  307.     //
  308.     // Make a GetData Apple event to send to the Finder
  309.     //
  310.     err = MakeAppleEvent(kAECoreSuite, kAEGetData, &pFinderTarget, 
  311.                 &finderEvent);
  312.     require(err == noErr, MakeAppleEvent);
  313.     
  314.     //
  315.     // Make an object specifier for the interesting file
  316.     //
  317.     err = MakeSpecifierForFile(hfsObj, &fileSpecifier);
  318.     require(err == noErr, MakeSpecifierForFile);
  319.     
  320.     //
  321.     // Make an icon family property specifier for the file
  322.     //
  323.     err = MakePropertySpecifierForSpecifier(pIconBitmap, &fileSpecifier, 
  324.                 &iconPropertySpecifier);
  325.     require(err == noErr, MakePropertySpecifierForSpecifier);
  326.     
  327.     //
  328.     // Stuff it in the Apple event and send it
  329.     //
  330.     err = AEPutParamDesc(&finderEvent, keyDirectObject, &iconPropertySpecifier);
  331.     require(err == noErr, AEPutParamDesc);
  332.  
  333.     err = SendAppleEvent(&finderEvent, &replyEvent,
  334.                 kAEWaitReply + kAECanInteract + kAECanSwitchLayer);
  335.     require(err == noErr, SendAppleEvent);
  336.     
  337.     //
  338.     // Now the Finder may have sent us an error number
  339.     //
  340.     err = AEGetParamPtr(&replyEvent, keyErrorNumber, typeLongInteger, 
  341.                         &returnType, &returnLong, sizeof(long), &returnSize);
  342.     if (err == noErr)
  343.         err = (OSErr) returnLong;
  344.  
  345.     else {        
  346.         //
  347.         // If not, get the icon family and build an icon suite
  348.         //
  349.         err = AEGetParamDesc(&replyEvent, keyDirectObject, typeWildCard, &iconFamily);    
  350.         require(err == noErr, AEGetParamDesc);
  351.     
  352.         err = BuildIconSuiteFromAEDesc(true, iconSuite, &iconFamily);
  353.     }
  354.  
  355.     //
  356.     // Clean up and exit
  357.     //
  358.     (void) AEDisposeDesc(&iconFamily);
  359.  
  360. AEGetParamDesc:
  361.     (void) AEDisposeDesc(&replyEvent);
  362.  
  363. SendAppleEvent:
  364. AEPutParamDesc:
  365.     (void) AEDisposeDesc(&iconPropertySpecifier);
  366.  
  367. MakePropertySpecifierForSpecifier:
  368.     (void) AEDisposeDesc(&fileSpecifier);
  369.  
  370. MakeSpecifierForFile:
  371.     (void) AEDisposeDesc(&finderEvent);
  372.  
  373. MakeAppleEvent:
  374. HaveScriptableFinder:
  375.     return err;
  376. }
  377.  
  378.  
  379. //----------------------------------------------------------------------------
  380. // GetSizeFromIconType
  381. //----------------------------------------------------------------------------
  382. static Size GetSizeFromIconType(DescType iconType)
  383. {
  384.     Size    size = -1;
  385.  
  386.     switch (iconType) {
  387.         case large8BitData:
  388.             size = kLarge8BitIconSize;
  389.             break;
  390.         case large4BitData:
  391.             size = kLarge4BitIconSize;        
  392.             break;
  393.         case large1BitMask:
  394.             size = kLargeIconSize;
  395.             break;
  396.         case small8BitData:
  397.             size = kSmall8BitIconSize;
  398.             break;
  399.         case small4BitData:
  400.             size = kSmall4BitIconSize;
  401.             break;
  402.         case small1BitMask:
  403.             size = kSmallIconSize;
  404.             break;
  405.     }
  406.     return size;
  407. }
  408.  
  409.  
  410. //----------------------------------------------------------------------------
  411. // BuildIconSuiteFromAEDesc
  412. //
  413. // OK, this uses the Apple Event Manager to pick the icon data out of the
  414. // 'ifam' AEDesc.
  415. //----------------------------------------------------------------------------
  416. OSErr BuildIconSuiteFromAEDesc(Boolean largeIcons, Handle *iconSuite, AEDesc *iconFam)
  417. {
  418.     OSErr        err;
  419.     Handle         suite, icon;
  420.     AERecord    rec;
  421.     Ptr            buffer;
  422.     DescType    large[3] = {large8BitData, large4BitData, large1BitMask};
  423.     DescType    small[3] = {small8BitData, small4BitData, small1BitMask};
  424.     DescType    *type, iconType, typeCode;
  425.     long        count;
  426.     Size        maxSize, size, iconSize;
  427.     Boolean        maskAdded;
  428.     DescType    maskType;
  429.  
  430.     maskAdded = false;
  431.     suite = NULL;
  432.     maxSize = kLarge8BitIconSize;
  433.  
  434.     if (largeIcons == true) {
  435.         type = large;
  436.         maskType = large1BitMask;
  437.     }
  438.     else {
  439.         type = small;
  440.         maskType = small1BitMask;
  441.     }
  442.  
  443.     buffer = NewPtr(maxSize);
  444.     require(buffer != NULL, NewPtr);
  445.     
  446.     err = NewIconSuite(&suite);
  447.     require(err == noErr, NewIconSuite);
  448.     
  449.     err = AECoerceDesc(iconFam, typeAERecord, (AEDesc *) &rec);
  450.     require(err == noErr, AECoerceDesc);
  451.     
  452.     for (count = 0; count < 3; count ++) {
  453.         //
  454.         // loop through the icons and grab the data from the AERecord for
  455.         // each type of icon we're interested in.
  456.         //
  457.         iconType = type[count];
  458.         size = GetSizeFromIconType(iconType);
  459.         err = AEGetKeyPtr(&rec, iconType, iconType, &typeCode, 
  460.                         buffer, maxSize, &iconSize);
  461.     
  462.         if (err == noErr) {
  463.             //
  464.             // We don't set the error code for this unless the NewHandle
  465.             // call fails, because it's possible that the 'ifam' doesn't
  466.             // have an icon for one that we're interested in.
  467.             //
  468.             icon = NewHandle(size);
  469.     
  470.             if (icon != NULL) {
  471.                 //
  472.                 // OK, the memory alloc succeeded and we have data. Copy
  473.                 // it into the allocated icon and add it to the suite. 
  474.                 // Set atLeastOne to true, to indicate later that we did
  475.                 // in fact add at least one icon to this suite.
  476.                 //
  477.                 BlockMoveData(buffer, *icon, size);
  478.                 err = AddIconToSuite(icon, suite, iconType);
  479.                 if ((err == noErr) && (iconType == maskType))
  480.                     maskAdded = true;
  481.             }
  482.             else
  483.                 err = memFullErr;
  484.         }
  485.     }
  486.  
  487.     (void) AEDisposeDesc(&rec);
  488.  
  489. AECoerceDesc:
  490.     if ((err != noErr) || (maskAdded == false)) {
  491.         //
  492.         // There was either an error in a memory allocation,  or something
  493.         // else went wrong (like no mask was added to the suite).  Get
  494.         // rid of the partially created suite.
  495.         //
  496.         DisposeIconSuite(suite, true);
  497.         suite = NULL;
  498.     }
  499.  
  500. NewIconSuite:
  501.     DisposePtr(buffer);
  502.  
  503. NewPtr:
  504.     *iconSuite = suite;
  505.     return err;
  506. }
  507.  
  508.  
  509. //----------------------------------------------------------------------------
  510. // MakeSpecifierForFile
  511. //----------------------------------------------------------------------------
  512. OSErr MakeSpecifierForFile(FSSpecPtr hfsObj, AEDesc *fileSpecifier)
  513. {
  514.     OSErr        err;
  515.     AEDesc        nullDesc, hfsData;
  516.     AliasHandle    fileAlias;
  517.  
  518.     //
  519.     // Create the file descriptor with the FSSpec passed in.
  520.     //
  521.     err = NewAlias(NULL, hfsObj, &fileAlias);
  522.     require(err == noErr, NewAlias);
  523.  
  524.     HLock((Handle) fileAlias);
  525.     err = AECreateDesc(typeAlias, (Ptr) *fileAlias, 
  526.                 GetHandleSize((Handle) fileAlias), &hfsData);
  527.     HUnlock((Handle) fileAlias);
  528.     DisposeHandle((Handle) fileAlias);
  529.     require(err == noErr, AECreateDesc);
  530.  
  531.     //
  532.     // Make the object specifier with a null container
  533.     // (i.e., "file of <null>", or just "file")
  534.     //
  535.     nullDesc.descriptorType = typeNull;
  536.     nullDesc.dataHandle = NULL;    
  537.     err = CreateObjSpecifier(typeWildCard, &nullDesc, 
  538.                 formAlias, &hfsData, false, fileSpecifier);
  539.  
  540. AECreateDesc:
  541. NewAlias:
  542.     return err;
  543. }
  544.  
  545.  
  546. //----------------------------------------------------------------------------
  547. // MakePropertySpecifierForSpecifier
  548. //----------------------------------------------------------------------------
  549. OSErr MakePropertySpecifierForSpecifier(DescType property, 
  550.             AEDesc *ofSpecifier, AEDesc *propertySpecifier)
  551. {
  552.     OSErr        err;
  553.     AEDesc        keyData;
  554.     
  555.     //
  556.     // Create a 'type' AEDesc with the desired property
  557.     //
  558.     err = AECreateDesc(typeType, (Ptr) &property, sizeof(DescType), &keyData);
  559.     require(err == noErr, AECreateDesc);
  560.  
  561.     //
  562.     // With it create a property specifier for the object specifier
  563.     // passed to us.
  564.     //
  565.     err = CreateObjSpecifier(cProperty, ofSpecifier, 
  566.                 formPropertyID, &keyData, false, propertySpecifier);
  567.  
  568.     (void) AEDisposeDesc(&keyData);    
  569. AECreateDesc:
  570.     return err;
  571. }
  572.  
  573.  
  574. //----------------------------------------------------------------------------
  575. // CloneMoveDescList
  576. //----------------------------------------------------------------------------
  577. OSErr CloneMoveDescList(AEDescList *objsToMove, FSSpecPtr nuLocation, 
  578.             Point globalPt, Boolean replace, Boolean moveFlag)
  579. {
  580.     OSErr        err;
  581.     AppleEvent    finderEvent;
  582.     DescType    copyMove;
  583.     
  584.     if (moveFlag == true)
  585.         copyMove = kAEMove;
  586.     else
  587.         copyMove = kAEClone;
  588.  
  589.     //
  590.     // Make a Copy/Move Apple event to send to the Finder
  591.     //
  592.     err = MakeAppleEvent(kAECoreSuite, copyMove, &pFinderTarget, 
  593.                 &finderEvent);
  594.     require(err == noErr, MakeAppleEvent);
  595.  
  596.     //
  597.     // Put the objects to move in the Apple Event as the direct object
  598.     //
  599.     err = AEPutParamDesc(&finderEvent, keyDirectObject, objsToMove);    
  600.     require(err == noErr, AEPutParamDesc);
  601.  
  602.     //
  603.     // Put in where the Finder should move the items
  604.     //    
  605.     err = AEPutParamPtr(&finderEvent, keyAEInsertHere, typeFSS, 
  606.                     (Ptr) nuLocation, sizeof(FSSpec));
  607.     require(err == noErr, AEPutParamPtr1);
  608.     
  609.     //
  610.     // Specify whether the Finder should replace any duplicates
  611.     //
  612.     err = AEPutParamPtr(&finderEvent, keyAEReplacing, typeBoolean, 
  613.                     (Ptr) &replace, sizeof(Boolean));
  614.     require(err == noErr, AEPutParamPtr2);
  615.     
  616.     //
  617.     // And where the Finder should put the items
  618.     //
  619.     err = AEPutParamPtr(&finderEvent, keyGlobalPositionList, typeQDPoint, 
  620.                     (Ptr) &globalPt, sizeof(Point));
  621.     require(err == noErr, AEPutParamPtr3);
  622.     
  623.     //
  624.     // Send it and return any error
  625.     //
  626.     err = SendAppleEvent(&finderEvent, NULL,
  627.                     kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer);
  628.  
  629. AEPutParamPtr3:
  630. AEPutParamPtr2:
  631. AEPutParamPtr1:
  632. AEPutParamDesc:
  633.     (void) AEDisposeDesc(&finderEvent);
  634. MakeAppleEvent:    
  635.     return err;
  636. }
  637.  
  638.  
  639. //-----------------------------------------------------------------------------
  640. // GetDropFSSpec
  641. //
  642. // Given a DragReference, this returns an FSSpec for where the 
  643. // item was dropped.  In most cases this is an FSSpec to a directory, but
  644. // if TrackDrag returns a userCancelledErr, it may have been dropped onto
  645. // an application.
  646. //-----------------------------------------------------------------------------
  647. OSErr GetDropFSSpec(DragReference theDrag, FSSpecPtr dropSpec)
  648. {
  649.     OSErr    err;
  650.     AEDesc    theDesc, newDesc;
  651.  
  652.     err = GetDropLocation(theDrag, &theDesc);
  653.     require(err == noErr, GetDropLocation);
  654.  
  655.     err = AECoerceDesc(&theDesc, typeFSS, &newDesc);
  656.     require(err == noErr, AECoerceDesc);
  657.  
  658.     BlockMoveData(*newDesc.dataHandle, dropSpec, sizeof(FSSpec));
  659.  
  660.     (void) AEDisposeDesc(&newDesc);
  661. AECoerceDesc:
  662.     (void) AEDisposeDesc(&theDesc);
  663. GetDropLocation:
  664.     return err;
  665. }
  666.